/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.venkatperi.gradle.api.java.archives.internal;
import com.github.venkatperi.gradle.api.java.archives.Attributes;
import com.github.venkatperi.gradle.api.java.archives.Manifest;
import com.github.venkatperi.gradle.api.java.archives.ManifestMergeDetails;
import com.github.venkatperi.gradle.api.java.archives.ManifestMergeSpec;
import groovy.lang.Closure;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.gradle.api.Action;
import org.gradle.api.internal.file.FileResolver;
import org.gradle.util.GUtil;
import org.gradle.util.WrapUtil;
import java.util.*;
public class DefaultManifestMergeSpec implements ManifestMergeSpec {
List<Object> mergePaths = new ArrayList<Object>();
private final List<Action<? super ManifestMergeDetails>> actions = new ArrayList<Action<? super ManifestMergeDetails>>();
public ManifestMergeSpec from(Object... mergePaths) {
GUtil.flatten(mergePaths, this.mergePaths);
return this;
}
public ManifestMergeSpec eachEntry(Action<? super ManifestMergeDetails> mergeAction) {
actions.add(mergeAction);
return this;
}
public ManifestMergeSpec eachEntry(Closure mergeAction) {
return eachEntry((Action<? super ManifestMergeDetails>) DefaultGroovyMethods.asType(mergeAction, Action.class));
}
public DefaultManifest merge(Manifest baseManifest, FileResolver fileResolver) {
DefaultManifest mergedManifest = new DefaultManifest(fileResolver);
mergedManifest.getAttributes().putAll(baseManifest.getAttributes());
mergedManifest.getSections().putAll(baseManifest.getSections());
for (Object mergePath : mergePaths) {
DefaultManifest manifestToMerge = createManifest(mergePath, fileResolver);
mergedManifest = mergeManifest(mergedManifest, manifestToMerge, fileResolver);
}
return mergedManifest;
}
private DefaultManifest mergeManifest(DefaultManifest baseManifest, DefaultManifest toMergeManifest, FileResolver fileResolver) {
DefaultManifest mergedManifest = new DefaultManifest(fileResolver);
mergeSection(null, mergedManifest, baseManifest.getAttributes(), toMergeManifest.getAttributes());
Set<String> allSections = GUtil.addSets(baseManifest.getSections().keySet(), toMergeManifest.getSections().keySet());
for (String section : allSections) {
mergeSection(section, mergedManifest,
GUtil.elvis(baseManifest.getSections().get(section), new DefaultAttributes()),
GUtil.elvis(toMergeManifest.getSections().get(section), new DefaultAttributes()));
}
return mergedManifest;
}
private void mergeSection(String section, DefaultManifest mergedManifest, Attributes baseAttributes, Attributes mergeAttributes) {
Map<String, Object> mergeOnlyAttributes = new LinkedHashMap<String, Object>(mergeAttributes);
Set<DefaultManifestMergeDetails> mergeDetailsSet = new LinkedHashSet<DefaultManifestMergeDetails>();
for (Map.Entry<String, Object> baseEntry : baseAttributes.entrySet()) {
Object mergeValue = mergeAttributes.get(baseEntry.getKey());
mergeDetailsSet.add(getMergeDetails(section, baseEntry.getKey(), baseEntry.getValue(), mergeValue));
mergeOnlyAttributes.remove(baseEntry.getKey());
}
for (Map.Entry<String, Object> mergeEntry : mergeOnlyAttributes.entrySet()) {
mergeDetailsSet.add(getMergeDetails(section, mergeEntry.getKey(), null, mergeEntry.getValue()));
}
for (DefaultManifestMergeDetails mergeDetails : mergeDetailsSet) {
for (Action<? super ManifestMergeDetails> action : actions) {
action.execute(mergeDetails);
}
addMergeDetailToManifest(section, mergedManifest, mergeDetails);
}
}
private DefaultManifestMergeDetails getMergeDetails(String section, String key, Object baseValue, Object mergeValue) {
String value = null;
String baseValueString = baseValue != null ? QuotedString.toString(baseValue) : null;
String mergeValueString = mergeValue != null ? QuotedString.toString(mergeValue) : null;
value = mergeValueString == null ? baseValueString : mergeValueString;
return new DefaultManifestMergeDetails(section, key, baseValueString, mergeValueString, value);
}
private void addMergeDetailToManifest(String section, DefaultManifest mergedManifest, DefaultManifestMergeDetails mergeDetails) {
if (!mergeDetails.isExcluded()) {
if (section == null) {
mergedManifest.attributes(WrapUtil.toMap(mergeDetails.getKey(), mergeDetails.getValue()));
} else {
mergedManifest.attributes(WrapUtil.toMap(mergeDetails.getKey(), mergeDetails.getValue()), section);
}
}
}
private DefaultManifest createManifest(Object mergePath, FileResolver fileResolver) {
if (mergePath instanceof DefaultManifest) {
return ((DefaultManifest) mergePath).getEffectiveManifest();
}
return new DefaultManifest(mergePath, fileResolver);
}
public List<Object> getMergePaths() {
return mergePaths;
}
}